﻿using System;
using Internal.Runtime.Models;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleSkill;

namespace Runtime.Models {

    /// <summary>
    /// 单元格数据
    /// </summary>
    public interface IDFR_BattleCellModelBase : IDFR_Model, IDFR_BattleGridElementModel {

        IDFR_BattleCellModelBaseSetter AsSetter();

        /// <summary>
        /// 拥有者玩家ID
        /// </summary>
        DFR_BattlePlayerID OwnerPlayerID { get; }

        /// <summary>
        /// 实例ID
        /// </summary>
        DFR_BattleEntityInstanceID EntityInstanceID { get; }

        /// <summary>
        /// 同化的内容实体ID，不要在逻辑中使用这个属性
        /// 由于在这个格子上加入内容往往需要在LockstepService的Attach完成时ContentEntityInstanceID才会有值
        /// 所以用这个属性在Attach之前就先赋值
        /// 所以这个属性主要用来给一些保存等持久化方面的操作取值
        /// </summary>
        DFR_BattleEntityID SynchronizedContentEntityID { get; set; }

        /// <summary>
        /// 是否可操作
        /// </summary>
        bool CanOperate();
        /// <summary>
        /// 是否<paramref name="playerID"/>可操作
        /// </summary>
        /// <param name="playerID">玩家ID</param>
        bool CanOperate(DFR_BattlePlayerID playerID);

        bool CanActiveBuff(DFR_BattlePlayerID playerID, IDFR_BattleBuffProvider buffProvider);
    }

    public interface IDFR_BattleCellModelBaseSetter : IDFR_BattleCellModelBase {

        /// <summary>
        /// 召唤
        /// </summary>
        /// <param name="contentInstanceID">内容实例ID</param>
        void Summon(DFR_BattleEntityInstanceID contentInstanceID);

        /// <summary>
        /// 遣散
        /// </summary>
        void Dismiss();
    }

    public abstract class DFR_BattleCellModelBase : DFR_Model, IDFR_BattleCellModelBase, IDFR_BattleCellModelBaseInternal, IDFR_BattleCellModelBaseSetter {

        public IDFR_BattleCellModelBaseSetter AsSetter() => this;

        public DFR_BattlePlayerID OwnerPlayerID { get; private set; } = DFR_BattlePlayerID.None;

        public DFR_BattleCellIndex Index { get; private set; } = DFR_BattleCellIndex.Invalid;

        public DFR_BattleCellAxis Axis { get; private set; }

        public DFR_BattleEntityInstanceID EntityInstanceID { get; private set; }

        [Autowired]
        private readonly IData<DFR_BattleEntityInstanceID> m_ContentEntityInstanceID;
        public IReadOnlyData<DFR_BattleEntityInstanceID> ContentEntityInstanceID => m_ContentEntityInstanceID;

        public DFR_BattleEntityID SynchronizedContentEntityID { get; set; }

        protected bool IsOperatable { get; private set; }

        public bool CanOperate() => CanOperate(BattleServiceBase.Instance.MyPlayerID);
        public bool CanOperate(DFR_BattlePlayerID playerID) => IsOperatable && OwnerPlayerID == playerID;

        public bool HasContent() => HasContent(BattleServiceBase.Instance.MyPlayerID);
        public bool HasContent(DFR_BattlePlayerID playerID) => CanOperate(playerID) && ContentEntityInstanceID.Value != DFR_BattleEntityInstanceID.Empty;

        public abstract bool CanActiveBuff(DFR_BattlePlayerID playerID, IDFR_BattleBuffProvider buffProvider);

        protected abstract bool Initialize();

        protected abstract DFR_BattleEntityInstanceID OwnerPlayerInstanceID { get; }

        protected virtual bool IsEnabled => true;

        void IDFR_BattleCellModelBaseInternal.Initialize(DFR_BattleCellIndex index, bool isOperatable, DFR_BattlePlayerID ownerPlayerID, DFR_BattleEntityType entityType) {
            EntityInstanceID = new() { ID = new() { TableID = index.Value, Type = entityType } };
            OwnerPlayerID = ownerPlayerID;
            EditBegin();
            Index = index;
            Axis = index.ToAxis();
            IsOperatable = isOperatable;
            if (Initialize()) {
            }
            EditDone();
        }


        protected abstract void Summon();
        void IDFR_BattleCellModelBaseSetter.Summon(DFR_BattleEntityInstanceID contentInstanceID) {
            m_ContentEntityInstanceID.Value = contentInstanceID;
            Summon();
        }

        protected abstract void Dismiss();
        void IDFR_BattleCellModelBaseSetter.Dismiss() {
            Dismiss();
            m_ContentEntityInstanceID.Value = DFR_BattleEntityInstanceID.Empty;
        }
    }
}

namespace Internal.Runtime.Models {

    public interface IDFR_BattleCellModelBaseInternal {

        void Initialize(DFR_BattleCellIndex index, bool isOperatable, DFR_BattlePlayerID ownerPlayerID, DFR_BattleEntityType entityType);
    }
}